home *** CD-ROM | disk | FTP | other *** search
/ Atari Mega Archive 1 / Atari Mega Archive - Volume 1.iso / telecomm / sticpsrc.lzh / SOURCE.ARC / ATARI_IO.C < prev    next >
C/C++ Source or Header  |  1990-07-22  |  9KB  |  469 lines

  1. /* Atari ST async I/O routines, used by "attach asy ..." */
  2. /* written by Rob Janssen, PE1CHL */
  3.  
  4. #include <stdio.h>
  5. #include <time.h>
  6. #ifndef __TURBOC__
  7. #include <osbind.h>            /* os interface defines */
  8. # ifdef MWC
  9. #  undef Rsconf
  10. #  define Rsconf(a,b,c,d,e,f)    (unsigned long) xbios(15,a,b,c,d,e,f)
  11. # endif
  12. #endif
  13.  
  14. #ifndef Bconmap
  15. # define Bconmap(dev)    (unsigned) xbios(44,dev) /* TT Xbios Bconmap() function */
  16. #endif
  17.  
  18. #include "global.h"
  19. #include "mbuf.h"
  20. #include "internet.h"
  21. #include "iface.h"
  22. #include "asy.h"
  23. #include "atari.h"
  24.  
  25. struct asy asy[ASY_MAX];
  26. unsigned nasy;
  27.  
  28. /* Interface list header */
  29. extern struct interface *ifaces;
  30.  
  31. static int asy_setbuf();
  32.  
  33. /* Initialize asynch port "dev" */
  34. int
  35. asy_init(dev,arg1,arg2,bufsize)
  36. int16 dev;
  37. char *arg1,*arg2;
  38. unsigned bufsize;
  39. {
  40.     register struct asy *ap;
  41.     unsigned tbufsize;
  42.     unsigned oldmap;
  43.     unsigned long rsconf;
  44.  
  45. #ifdef DEBUG
  46.     printf("asy_init(%d,%s,%s,%d)\n",dev,arg1,arg2,bufsize); fflush(stdout);
  47. #endif
  48.     ap = &asy[dev];
  49.     ap->addr = atoi(arg1);            /* device number */
  50.     ap->vec = htoi(arg2);            /* used for mode flags */
  51.  
  52.     if (ap->addr == 0 || ap->addr == 2)    /* backward compatability... */
  53.         ap->addr++;            /* (old devs 0,2 are now 1,3) */
  54.  
  55.     if (ap->addr == 4 || ap->addr == 5 || ap->addr > 15) {
  56.         printf("asy%d: Bad address %d\n",dev,ap->addr);
  57.         return -1;
  58.     }
  59.  
  60. #ifdef DEBUG
  61.     printf("asy_init: ap->addr=%u, ap->vec=%u\n",ap->addr,ap->vec); fflush(stdout);
  62. #endif
  63.     /* devno's above 5 need Bconmap() to be configured */
  64.  
  65.     if (ap->addr >= MODEM1) {
  66.         if ((oldmap = Bconmap(ap->addr)) >= 44) {
  67.             printf("Warning: cannot configure asy dev %d\n",ap->addr);
  68.             return 0;
  69.         }
  70.     }
  71.  
  72.     /* determine buffering.     everybody has receive buffer, but a transmit */
  73.     /* buffer is NOT used for MIDI and RS232-direct */
  74.  
  75.     tbufsize = 0;                /* default no tx buffer */
  76.  
  77.     switch (ap->addr)
  78.     {
  79.     case RS232:
  80.         if (ap->vec & 1)        /* direct buffer access? */
  81.             goto no_txbuf;
  82.  
  83.     default:
  84.         if ((tbufsize = bufsize) > 1024) /* set tx buffer */
  85.             tbufsize = 1024;
  86.  
  87.     case MIDI:
  88.     no_txbuf:
  89.         if (asy_setbuf(ap,bufsize,tbufsize)) {
  90.             if (ap->addr >= MODEM1)
  91.                 Bconmap(oldmap);
  92.  
  93.             return -1;
  94.         }
  95.         break;
  96.     }
  97.  
  98.     if (ap->addr != MIDI) {
  99.         rsconf = Rsconf(-1,-1,-1,-1,-1,-1); /* read present config */
  100. #ifdef DEBUG
  101.         printf("asy_init: rsconf was %08lx\n",rsconf); fflush(stdout);
  102. #endif
  103.  
  104.         /* setup for no flow, 8 bits, no parity, leave rest as-is */
  105.  
  106.         Rsconf(-1,0,(int) ((rsconf>>24) & 0x81) | 0x08,-1,(int) (rsconf>>8) & 0x77,-1);
  107.     }
  108.  
  109.     if (ap->addr >= MODEM1)
  110.         Bconmap(oldmap);
  111.  
  112.     return 0;
  113. }
  114.  
  115. static int
  116. asy_setbuf (ap,rbufsize,tbufsize)
  117. register struct asy *ap;
  118. unsigned rbufsize,tbufsize;
  119.  
  120. {
  121.     register struct iorec *ip;
  122.     char *rbufp,*tbufp;
  123.     char i_state;
  124.  
  125. #ifdef DEBUG
  126.     printf("asy_setbuf: addr=%u rbufsize=%u tbufsize=%u\n",ap->addr,rbufsize,tbufsize); fflush(stdout);
  127. #endif
  128.     if (ap->addr == MIDI)
  129.         tbufsize = 0;            /* MIDI can't have tx buf */
  130.  
  131.     if ((rbufp = malloc(rbufsize)) == NULLCHAR){
  132.         printf("asy %d: No space for rx buffer\n",ap->addr);
  133.         return -1;
  134.     }
  135.  
  136.     if (tbufsize != 0){
  137.         if ((tbufp = malloc(tbufsize)) == NULLCHAR){
  138.             free(rbufp);
  139.             printf("asy %d: No space for tx buffer\n",ap->addr);
  140.             return -1;
  141.         }
  142.     }
  143.  
  144.     ip = (struct iorec *) Iorec((ap->addr == MIDI)? 2 : 0);
  145.  
  146.     ap->in = ip;
  147.     ap->out = ip + 1;
  148.  
  149.     i_state = disable();
  150.  
  151.     /* Save original IOREC values */
  152.     memcpy(&ap->oldin,ap->in,sizeof(struct iorec));
  153.     if (ap->addr != MIDI)
  154.         memcpy(&ap->oldout,ap->out,sizeof(struct iorec));
  155.  
  156.     /* Set up receiver FIFO */
  157.     ap->in->ibuf = rbufp;
  158.     ap->in->ibufsiz = rbufsize;
  159.     ap->in->ibufhd = ap->in->ibuftl = 0;
  160.     ap->in->ibuflow = 0;
  161.     ap->in->ibufhi = rbufsize;
  162.  
  163.     if (tbufsize != 0) {
  164.         /* Set up transmitter FIFO */
  165.         ap->out->ibuf = tbufp;
  166.         ap->out->ibufsiz = tbufsize;
  167.         ap->out->ibufhd = ap->out->ibuftl = 0;
  168.         ap->out->ibuflow = 0;
  169.         ap->out->ibufhi = tbufsize;
  170.     }
  171.  
  172.     restore(i_state);
  173.  
  174.     return 0;
  175. }
  176.  
  177. void
  178. asy_stop(iface)
  179. struct interface *iface;
  180. {
  181.     register struct asy *ap;
  182.     char i_state;
  183.  
  184. #ifdef DEBUG
  185.     printf("asy_stop(0x%lx), dev=%d\n",iface,iface->dev);
  186.     fflush(stdout);
  187. #endif
  188.  
  189.     ap = &asy[iface->dev];
  190.  
  191.     if (ap->in == NULL)        /* no Iorec setup done? */
  192.         return;
  193.  
  194.     if (ap->addr != MIDI)
  195.         while (ap->out->ibufhd != ap->out->ibuftl)
  196.             ;        /* wait until all transmitted */
  197.  
  198.     /* Restore old iorecs */
  199.  
  200.     i_state = disable();
  201.  
  202.     free(ap->in->ibuf);        /* free the buffer */
  203.     memcpy(ap->in,&ap->oldin,sizeof(struct iorec));
  204.  
  205.     if (ap->addr != MIDI)
  206.     {
  207. #if 0
  208.         free(ap->out->ibuf);    /* transmit buffer too */
  209. #endif
  210.         memcpy(ap->out,&ap->oldout,sizeof(struct iorec));
  211.     }
  212.  
  213.     restore(i_state);
  214. }
  215.  
  216. /* Asynchronous line I/O control */
  217. asy_ioctl(interface,argc,argv)
  218. struct interface *interface;
  219. int argc;
  220. char *argv[];
  221. {
  222.     if(argc < 1){
  223.         printf("%d\r\n",asy[interface->dev].speed);
  224.         return 0;
  225.     }
  226.     return asy_speed(interface->dev,atoi(argv[0]));
  227. }
  228.  
  229. /* Set asynch line speed */
  230. int
  231. asy_speed(dev,speed)
  232. int dev;
  233. unsigned int speed;
  234. {
  235.     register struct asy *ap;
  236.     register int sp;
  237.     unsigned oldmap;
  238.     long sav_ssp;
  239.  
  240. #ifdef DEBUG
  241.     printf("asy_speed(%d,%u)\n",dev,speed); fflush(stdout);
  242. #endif
  243.  
  244.     if(speed == 0 || dev >= nasy)
  245.         return -1;
  246.  
  247.     ap = &asy[dev];
  248.  
  249.     switch (ap->addr)
  250.     {
  251.     case MIDI:
  252.         /* midi can run on 500000 or 614400Hz clock (hardware mod) */
  253.         switch (speed)
  254.         {
  255.         case 0x9600:        /* = 38400 unsigned... */
  256.         case 31250:
  257.         case 16:        /* divide-by-16 */
  258.             sp = 0x95;
  259.             break;
  260.         case 9600:
  261.         case 7812:
  262.         case 64:        /* divide-by-64 */
  263.             sp = 0x96;
  264.             break;
  265.         default:
  266.             printf("asy: bad speed on MIDI\n");
  267.             return -1;
  268.         }
  269.  
  270.         sav_ssp = Super(NULL);        /* access chip */
  271.         *((char *) 0xfffffc04L) = 0x03; /* RESET it */
  272.         *((char *) 0xfffffc04L) = sp;    /* set new program */
  273.         Super(sav_ssp);
  274.         break;
  275.  
  276.     default:
  277.         switch (speed)
  278.         {
  279.         case 19200:  sp = 0; break;
  280.         case  9600:  sp = 1; break;
  281.         case  4800:  sp = 2; break;
  282.         case  2400:  sp = 4; break;
  283.         case  1200:  sp = 7; break;
  284.         case   600:  sp = 8; break;
  285.         case   300:  sp = 9; break;
  286.         default:
  287.             if (speed > 32) {
  288.                 printf("asy: bad speed on RS232\n");
  289.                 return -1;
  290.             }
  291.             sp = speed;
  292.             break;
  293.         }
  294.  
  295.         /* devno's above 5 need Bconmap() to be configured */
  296.  
  297.         if (ap->addr >= MODEM1) {
  298.             if ((oldmap = Bconmap(ap->addr)) >= 44) {
  299.                 printf("Warning: cannot set speed for asy dev %d\n",ap->addr);
  300.                 return 0;
  301.             }
  302.         }
  303.  
  304.         Rsconf(sp,-1,-1,-1,-1,-1);    /* set new speed */
  305.  
  306.         if (ap->addr >= MODEM1)
  307.             Bconmap(oldmap);
  308.  
  309.         break;
  310.     }
  311.  
  312.     ap->speed = speed;
  313.  
  314.     return 0;
  315. }
  316.  
  317. /* Send a buffer to serial transmitter */
  318. asy_output(dev,buf,cnt)
  319. unsigned dev;
  320. char *buf;
  321. unsigned short cnt;
  322. {
  323.     register struct asy *ap;
  324.     register struct iorec *ip;
  325.     long sav_ssp;
  326.  
  327. #ifdef XDEBUG
  328.     int i;
  329.     printf("asy_output(%d,0x%lx,%d) data=",dev,buf,cnt);
  330.     for (i = 0; i < cnt; i++)
  331.         printf("%02x ",buf[i] & 0xff);
  332.     printf("\n");
  333.     fflush(stdout);
  334. #endif
  335.  
  336.     if (dev >= nasy || cnt == 0)    /* these "cannot happen" */
  337.         return;
  338.  
  339.     ap = &asy[dev];
  340.  
  341.     switch (ap->addr)
  342.     {
  343.     case MIDI:
  344.         Midiws(cnt - 1,buf);    /* write MIDI (unbuffered...) */
  345.         break;
  346.  
  347.     case RS232:
  348.         if (ap->vec & 1) {
  349.             ip = ap->out;
  350.  
  351.             if(ip->ibufhd != ip->ibuftl)
  352.                 return; /* Already busy */
  353.  
  354.             /* fake the output record to transmit data */
  355.             ip->ibuf = buf;
  356.             ip->ibufsiz = cnt;
  357.             ip->ibufhd = 0;
  358.             ip->ibuftl = cnt - 1;
  359.             ip->ibuflow = 0;
  360.             ip->ibufhi = cnt + 1;
  361.  
  362.             sav_ssp = Super(NULL); /* supervisor mode to access chip */
  363.  
  364.             /* kick the chip to start interrupts */
  365.             *((char *) (0xfffffa01L+46)) = ip->ibuf[0];
  366.  
  367.             Super(sav_ssp); /* back to user mode */
  368.             break;
  369.         }
  370.  
  371.     default:
  372.         do {
  373.             Bconout(ap->addr,*buf++);
  374.         }
  375.         while (--cnt);
  376.  
  377.         break;
  378.     }
  379. }
  380.  
  381. /* Receive characters from asynch line
  382.  * Returns count of characters read
  383.  */
  384. int16
  385. asy_recv(dev,buf,cnt)
  386. int dev;
  387. register char *buf;
  388. unsigned cnt;
  389. {
  390.     unsigned tot;
  391.     register struct asy *ap;
  392.     register struct iorec *ip;
  393. #ifdef XDEBUG
  394.     int i;
  395.     char *b = buf;
  396. #endif
  397.  
  398.     ap = &asy[dev];
  399.